package hyl.core.db;

import hyl.core.MyFun;
import hyl.core.conf.MyConfig;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * 数据库连接池对象 Created by zdy on 2018-2-16.
 */
public class DBPool {
	public static final Logger Log = LoggerFactory.getLogger(DBPool.class);
	private static volatile DBPool dbpool;
	private Map<String, MyDataSource> dataSources = new ConcurrentHashMap<>();

	// static int _是否异常后一直尝试连接 = 0;
	/**
	 * 在构造函数初始化的时候获取数据库连接
	 */
	private DBPool() {
		try {
			// 连接数据库最长用时限制（秒）,默认不限制，程序继续执行.
			// DriverManager.setLoginTimeout(1);
			// System.out.println(text);
			Map<String, JSONObject> conf = MyConfig.getConfOfDb();
			for (Map.Entry<String, JSONObject> entry : conf.entrySet()) {
				JSONObject pp = entry.getValue();
				String driverClassName = pp.getString("jdbc.driverClassName");
				// 0 只尝试2遍 1 一直尝试
				// _是否异常后一直尝试连接 = MyFun.str2int(pp.getString("keepalive"));
				int 最大连接数 = MyFun.str2int(pp.getString("maxPoolSize"));
				if (最大连接数 == 0)
					最大连接数 = MyFun.str2int(pp.getString("最大连接数"));
				// int 连接间隔 = MyFun.str2int(pp.get("acquireRetryDelay"));
				// int 重试次数 = MyFun.str2int(pp.get("acquireRetryAttempts"));
				MyDataSource ds = MyDataSource3.newInstance(entry.getKey(), driverClassName, 最大连接数);
				if (ds == null) {
					continue;
				}
				if (pp.containsKey("jdbc.url")) {
					setConn(ds, entry.getKey(), pp);
				} else if (pp.containsKey("jdbc.urls")) {
					setConns(ds, entry.getKey(), pp);
				}
			}
		} catch (Exception e) {
			Log.info("jdbc中连接配置有异常" + e.getMessage());
		}
	}

	void setConn(MyDataSource ds, String key, JSONObject pp) {
		String url = pp.getString("jdbc.url");
		String username = pp.getString("jdbc.username");
		String password = pp.getString("jdbc.password");
		System.out.println(password);
		if (ds.ini(url, username, password)) {
			Log.info("jdbc中【" + key + "】配置加载成功");
			ds.cb启动监控任务(key);
			dataSources.put(key, ds);
		} else {
			Log.error("jdbc中【" + key + "】配置加载异常");
		}
	}

	void setConns(MyDataSource ds, String key, JSONObject pp) {
		JSONArray pps = pp.getJSONArray("jdbc.urls");
		/** 通过属性文件获取数据库连接的参数值 **/
		/** 获取属性文件中的值 **/
		for (int i = 0; i < pps.size(); i++) {
			JSONObject o = pps.getJSONObject(i);
			String url = o.getString("url");
			String user = o.getString("user");
			String pass = o.getString("pass");
			ds.addConnUrl(url, user, pass);
		}
		if (ds.ini(ds.getConnUrl(0))) {
			Log.info("jdbc中【" + key + "】配置加载成功");
			ds.cb启动监控任务(key);
			dataSources.put(key, ds);
		} else {
			Log.error("jdbc中【" + key + "】配置加载异常");
		}
	}

	public static void exitAll() {
		if (dbpool == null)
			return;
		for (String key : dbpool.dataSources.keySet()) {
			MyDataSource cpds = dbpool.dataSources.get(key);
			try {
				cpds.exitAll();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		dbpool.dataSources.clear();
	}

	/**
	 * 获取数据库连接对象，单例
	 *
	 * @return
	 */
	public static DBPool getInstance() {
		if (dbpool == null)
			dbpool = new DBPool();
		return dbpool;
	}

	/**
	 * 
	 * @title: checkConfig @description: 如果没有有效的配置那么返回 false，否则返回true @return
	 *         boolean @throws
	 */
	public boolean checkConfig() {
		if (dataSources.isEmpty())
			return false;
		else
			return true;
	}

	/**
	 * 获取数据库连接
	 *
	 * @return 数据库连接
	 */
	public final synchronized MyConnection getConnection(String db) {
		try {
			return dataSources.get(db).getConnection();
		} catch (Exception e) {
			Log.error(db + "连接不存在，请检查原因：连接池配置错误或服务关闭或网络断开");
		}
		return null;
	}

	public final synchronized MyDataSource getDataSource(String db) {
		return dataSources.get(db);
	}

	/**
	 * 默认是手动提交模式 type
	 */
	public final synchronized MyDB getCommitDB(String db) {
		return MyDB.createCommitDB(db);
	}

	/**
	 * 默认是手动提交模式
	 */
	public final synchronized MyDB getDB(String db) {
		return MyDB.createDB(db);
	}

	/** 每间隔一定时间period(单位:毫秒)自动提交 */
	public final synchronized MyDB getTimerDB(String db, int period) {
		return MyDB.createTimerDB(db, period);
	}

	/** 每间隔一定时间period(单位:毫秒)自动提交 默认每2秒提交 */
	public final synchronized MyDB getTimerDB(String db) {
		return MyDB.createTimerDB(db);
	}
}
